/*
 * PackageVulnerabilityModalDialog.java
 *
 * Copyright (C) 2025 by Posit Software, PBC
 *
 * Unless you have received this program directly from Posit Software pursuant
 * to the terms of a commercial license agreement with Posit Software, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.studio.client.workbench.views.packages.ui;

import java.util.List;

import org.rstudio.core.client.widget.ModalDialogBase;
import org.rstudio.core.client.widget.ThemedButton;
import org.rstudio.studio.client.RStudioGinjector;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.common.HelpLink;
import org.rstudio.studio.client.workbench.views.console.events.SendToConsoleEvent;
import org.rstudio.studio.client.workbench.views.packages.model.PackageInfo;
import org.rstudio.studio.client.workbench.views.packages.model.PackageVulnerabilityTypes.PackageVulnerability;
import org.rstudio.studio.client.workbench.views.packages.model.PackageVulnerabilityTypes.PackageVulnerabilityEvent;
import org.rstudio.studio.client.workbench.views.packages.model.PackageVulnerabilityTypes.PackageVulnerabilityEventList;

import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class PackageVulnerabilityModalDialog extends ModalDialogBase
{
    public PackageVulnerabilityModalDialog(PackageInfo info,
                                           List<PackageVulnerability> pvList)
    {
        super(Roles.getDialogRole());

        setText(info.getName() + " " + info.getVersion() + ": Known Vulnerabilities");

        info_ = info;
        pvList_ = pvList;
        index_ = 0;

        container_ = new VerticalPanel();

        panel_ = new HTML();
        panel_.setSize("500px", "400px");
        panel_.getElement().getStyle().setProperty("userSelect", "text");
        container_.add(panel_);

        moreInfoLink_ = new HelpLink();
        container_.add(moreInfoLink_);

        prevButton_ = new ThemedButton("Previous", new ClickHandler()
        {
            @Override
            public void onClick(ClickEvent event)
            {
                index_ = index_ - 1;
                refresh();
            }
        });

        nextButton_ = new ThemedButton("Next", new ClickHandler() 
        {
            @Override
            public void onClick(ClickEvent event)
            {
                index_ = index_ + 1;
                refresh();
            }
        });

        updateButton_ = new ThemedButton("Update", new ClickHandler()
        {
            @Override
            public void onClick(ClickEvent event)
            {
                events_.fireEvent(new SendToConsoleEvent(
                    "install.packages(\"" + info_.getName() + "\")",
                    true));
                closeDialog();
            }

            private final EventBus events_ = RStudioGinjector.INSTANCE.getEventBus();
        });

        if (pvList_.size() > 1)
        {
            addLeftButton(prevButton_, "previous");
            addLeftButton(nextButton_, "next");
        }

        addOkButton(updateButton_);
        addCancelButton();
    }

    private void refresh()
    {
        prevButton_.setEnabled(index_ > 0);
        nextButton_.setEnabled(index_ < pvList_.size() - 1);

        panel_.getElement().getStyle().setMarginLeft(24, Unit.PX);
        panel_.getElement().getStyle().setMarginRight(24, Unit.PX);

        SafeHtmlBuilder sb = new SafeHtmlBuilder();

        PackageVulnerability vuln = pvList_.get(index_);
        sb.append(TEMPLATES.render(vuln.id, vuln.summary, vuln.details));

        if (vuln.ranges.getLength() > 0)
        {
            sb.appendHtmlConstant("<h3>Events</h3>");

            sb.appendHtmlConstant("<ul>");
            for (PackageVulnerabilityEventList eventList : vuln.ranges.asList())
            {
                for (PackageVulnerabilityEvent event : eventList.events.asList())
                {
                    if (event.introduced != null)
                    {
                        sb.append(TEMPLATES.renderEvent("Introduced", info_.getName(), event.introduced));
                    }

                    if (event.fixed != null)
                    {
                        sb.append(TEMPLATES.renderEvent("Fixed", info_.getName(), event.fixed));
                    }
                }
            }
            sb.appendHtmlConstant("</ul>");
        }

        panel_.setHTML(sb.toSafeHtml());

        moreInfoLink_.setCaption(vuln.id);
        moreInfoLink_.setLink("https://osv.dev/vulnerability/" + vuln.id, false);
    }

    @Override
    protected Widget createMainWidget()
    {
        return container_;
    }

    @Override
    public void showModal()
    {
        super.showModal();
        refresh();
    }

    interface Templates extends SafeHtmlTemplates
    {
        @Template("""
           <h1>{0}</h1>
           <h2>{1}</h2>
           <h3>Details</h3>
           <p>{2}</p>
        """)
        SafeHtml render(String id, String summary, String details);

        @Template("<li>{0} in {1} {2}.</li>")
        SafeHtml renderEvent(String eventType, String packageName, String packageVersion);
    }

    private final PackageInfo info_;
    private final List<PackageVulnerability> pvList_;
    private int index_;

    private final VerticalPanel container_;
    private final HTML panel_;
    private final ThemedButton prevButton_;
    private final ThemedButton nextButton_;
    private final ThemedButton updateButton_;
    private final HelpLink moreInfoLink_;


    private static final Templates TEMPLATES = GWT.create(Templates.class);
}
